﻿/*
 * Copyright (c) Martin Kinkelin
 *
 * See the "License.txt" file in the root directory for infos
 * about permitted and prohibited uses of this code.
 */

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Diagnostics;
using Jarf.Properties;

namespace Jarf
{
	/// <summary>
	/// Main form of the application.
	/// </summary>
	public partial class MainForm : BaseForm
	{
		/// <summary>
		/// Gets the currently selected backup task or null if none is selected.
		/// </summary>
		private BackupTask SelectedTask
		{
			get
			{
				return (listView1.SelectedIndices.Count == 0 ? null :
					(BackupTask)listView1.SelectedItems[0].Tag);
			}
		}



		public MainForm()
		{
			InitializeComponent();

			List<BackupTask> tasks;

			try
			{
				tasks = BackupTaskManager.Instance.LoadTasks();

				foreach (BackupTask task in tasks)
				{
					AddListViewItem(task);
				}
			}
			catch
			{
				MessageBox.Show("The \"Tasks.xml\" file is corrupt, the tasks could not be loaded.", "Parsing error",
					MessageBoxButtons.OK, MessageBoxIcon.Error);
			}

			// select the first item
			if (listView1.Items.Count > 0)
				listView1.SelectedIndices.Add(0);
		}


		private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
		{
			if (rsyncOperationControl1.IsRunning && !rsyncOperationControl1.Abort())
			{
				e.Cancel = true;
				return;
			}

			List<BackupTask> tasks = new List<BackupTask>(listView1.Items.Count);

			foreach (ListViewItem item in listView1.Items)
			{
				tasks.Add((BackupTask)item.Tag);
			}

			try
			{
				BackupTaskManager.Instance.SaveTasks(tasks);
			}
			catch
			{
				if (MessageBox.Show("Error while trying to save the tasks to disk.\nDo you still want to exit?", "Saving error",
					MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button2) != DialogResult.Yes)
				{
					e.Cancel = true;
				}
			}
		}


		private void listView1_SelectedIndexChanged(object sender, EventArgs e)
		{
			editButton.Enabled = removeButton.Enabled = (listView1.SelectedIndices.Count > 0);
			scheduleButton.Enabled = (listView1.SelectedIndices.Count > 0);

			backupButton.Enabled = restoreButton.Enabled =
				(listView1.SelectedIndices.Count > 0 && !rsyncOperationControl1.IsRunning);
		}

		private void listView1_DoubleClick(object sender, EventArgs e)
		{
			// simulate pressing the edit button if an item is double-clicked
			if (listView1.SelectedIndices.Count > 0)
				editButton.PerformClick();
		}


		private void addButton_Click(object sender, EventArgs e)
		{
			BackupTask task = new BackupTask();

			using (BackupTaskDialog dialog = new BackupTaskDialog(task))
			{
				if (dialog.ShowDialog(this) == DialogResult.Yes)
				{
					AddListViewItem(task);

					// select the newly added item
					listView1.SelectedIndices.Clear();
					listView1.SelectedIndices.Add(listView1.Items.Count - 1);
				}
			}
		}

		private void editButton_Click(object sender, EventArgs e)
		{
			BackupTask task = SelectedTask;

			using (BackupTaskDialog dialog = new BackupTaskDialog(task))
			{
				if (dialog.ShowDialog(this) == DialogResult.Yes)
					UpdateListViewItem(task);
			}
		}

		private void removeButton_Click(object sender, EventArgs e)
		{
			if (MessageBox.Show("Are you sure you want to remove the selected backup task?", "Confirmation",
				MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
				return;

			listView1.Items.RemoveAt(listView1.SelectedIndices[0]);
		}


		private void scheduleButton_Click(object sender, EventArgs e)
		{
			using (ScheduleDialog dialog = new ScheduleDialog(SelectedTask))
			{
				dialog.ShowDialog(this);
			}
		}


		private void backupButton_Click(object sender, EventArgs e)
		{
			rsyncOperationControl1.Start(SelectedTask, false, Settings.Default.SimulateFirst);
		}

		private void restoreButton_Click(object sender, EventArgs e)
		{
			rsyncOperationControl1.Start(SelectedTask, true, Settings.Default.SimulateFirst);
		}

		/// <summary>
		/// Invoked when an operation has been started.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void rsyncOperationControl1_Started(object sender, EventArgs e)
		{
			backupButton.Enabled = false;
			restoreButton.Enabled = false;
		}

		/// <summary>
		/// Invoked when an operation has been aborted or has completed erroneously.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void rsyncOperationControl1_Aborted(object sender, EventArgs e)
		{
			backupButton.Enabled = restoreButton.Enabled = (listView1.SelectedIndices.Count > 0);
		}

		/// <summary>
		/// Invoked when an operation has completed successfully.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void rsyncOperationControl1_Completed(object sender, EventArgs e)
		{
			backupButton.Enabled = restoreButton.Enabled = (listView1.SelectedIndices.Count > 0);

			if (!rsyncOperationControl1.Restoring)
				UpdateListViewItem(rsyncOperationControl1.Task);
		}


		/// <summary>
		/// Creates an appropriate ListViewItem and adds it to the ListView.
		/// </summary>
		/// <param name="task"></param>
		private void AddListViewItem(BackupTask task)
		{
			ListViewItem item = new ListViewItem();
			item.Tag = task;
			item.ImageIndex = 0;
			item.SubItems.Add(task.Source);
			item.SubItems.Add(task.Destination);
			item.SubItems.Add(task.LastBackup.HasValue ? task.LastBackup.Value.ToString("g") : "Never");

			listView1.Items.Add(item);
		}

		/// <summary>
		/// Updates the corresponding item in the ListView after a backup task
		/// has been modified.
		/// </summary>
		/// <param name="task"></param>
		private void UpdateListViewItem(BackupTask task)
		{
			foreach (ListViewItem item in listView1.Items)
			{
				if (item.Tag == task)
				{
					item.SubItems[1].Text = task.Source;
					item.SubItems[2].Text = task.Destination;
					item.SubItems[3].Text = (task.LastBackup.HasValue ?
						task.LastBackup.Value.ToString("g") : "Never");

					break;
				}
			}
		}
	}
}
